package logger

import (
	"context"
	"encoding/json"
	"fmt"
	"runtime"
	"time"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"

	"goldtree/internal/entity"
)

// LogLevel 日志级别
type LogLevel string

const (
	LevelDebug LogLevel = "DEBUG"
	LevelInfo  LogLevel = "INFO"
	LevelWarn  LogLevel = "WARN"
	LevelError LogLevel = "ERROR"
	LevelFatal LogLevel = "FATAL"
)

// Logger 系统日志器
type Logger struct {
	module string
}

// New 创建新的日志器
func New(module string) *Logger {
	return &Logger{module: module}
}

// LogContext 日志上下文
type LogContext struct {
	RequestId string      `json:"request_id,omitempty"`
	UserId    int         `json:"user_id,omitempty"`
	IP        string      `json:"ip,omitempty"`
	UserAgent string      `json:"user_agent,omitempty"`
	Action    string      `json:"action,omitempty"`
	Data      interface{} `json:"data,omitempty"`
	CostTime  int64       `json:"cost_time,omitempty"` // 毫秒
	Error     string      `json:"error,omitempty"`
}

// Debug 调试日志
func (l *Logger) Debug(ctx context.Context, message string, data ...interface{}) {
	l.log(ctx, LevelDebug, message, data...)
}

// Info 信息日志
func (l *Logger) Info(ctx context.Context, message string, data ...interface{}) {
	l.log(ctx, LevelInfo, message, data...)
}

// Warn 警告日志
func (l *Logger) Warn(ctx context.Context, message string, data ...interface{}) {
	l.log(ctx, LevelWarn, message, data...)
}

// Error 错误日志
func (l *Logger) Error(ctx context.Context, message string, data ...interface{}) {
	l.log(ctx, LevelError, message, data...)
}

// Fatal 致命错误日志
func (l *Logger) Fatal(ctx context.Context, message string, data ...interface{}) {
	l.log(ctx, LevelFatal, message, data...)
}

// log 内部日志方法
func (l *Logger) log(ctx context.Context, level LogLevel, message string, data ...interface{}) {
	// 构建日志上下文
	logCtx := l.buildLogContext(ctx, data...)
	
	// 转换为JSON字符串
	contextJson, _ := json.Marshal(logCtx)
	
	// 输出到控制台
	switch level {
	case LevelDebug:
		g.Log().Debug(ctx, fmt.Sprintf("[%s] %s", l.module, message), string(contextJson))
	case LevelInfo:
		g.Log().Info(ctx, fmt.Sprintf("[%s] %s", l.module, message), string(contextJson))
	case LevelWarn:
		g.Log().Warning(ctx, fmt.Sprintf("[%s] %s", l.module, message), string(contextJson))
	case LevelError:
		g.Log().Error(ctx, fmt.Sprintf("[%s] %s", l.module, message), string(contextJson))
	case LevelFatal:
		g.Log().Fatal(ctx, fmt.Sprintf("[%s] %s", l.module, message), string(contextJson))
	}
	
	// 异步保存到数据库
	go l.saveToDatabase(ctx, level, message, logCtx)
}

// buildLogContext 构建日志上下文
func (l *Logger) buildLogContext(ctx context.Context, data ...interface{}) *LogContext {
	logCtx := &LogContext{}
	
	// 从HTTP请求中获取信息
	if r := g.RequestFromCtx(ctx); r != nil {
		logCtx.RequestId = r.GetHeader("X-Request-Id")
		logCtx.IP = r.GetClientIp()
		logCtx.UserAgent = r.GetHeader("User-Agent")
	}
	
	// 处理额外数据
	if len(data) > 0 {
		if len(data) == 1 {
			logCtx.Data = data[0]
		} else {
			logCtx.Data = data
		}
	}
	
	return logCtx
}

// saveToDatabase 保存日志到数据库
func (l *Logger) saveToDatabase(ctx context.Context, level LogLevel, message string, logCtx *LogContext) {
	defer func() {
		if r := recover(); r != nil {
			g.Log().Error(ctx, "保存日志到数据库失败", r)
		}
	}()
	
	contextJson, _ := json.Marshal(logCtx)
	
	logEntity := &entity.SystemLog{
		Level:     string(level),
		Module:    l.module,
		Message:   message,
		Context:   string(contextJson),
		IpAddress: logCtx.IP,
		UserAgent: logCtx.UserAgent,
	}
	
	// 这里需要实现SystemLog的DAO
	// dao.SystemLog.Insert(ctx, logEntity)
	_ = logEntity
}

// LogOperation 记录操作日志
func (l *Logger) LogOperation(ctx context.Context, action string, data interface{}, err error) {
	logCtx := l.buildLogContext(ctx)
	logCtx.Action = action
	logCtx.Data = data
	
	if err != nil {
		logCtx.Error = err.Error()
		l.Error(ctx, fmt.Sprintf("操作失败: %s", action), logCtx)
	} else {
		l.Info(ctx, fmt.Sprintf("操作成功: %s", action), logCtx)
	}
}

// LogAPIRequest 记录API请求日志
func (l *Logger) LogAPIRequest(ctx context.Context, r *ghttp.Request, startTime time.Time, err error) {
	costTime := time.Since(startTime).Milliseconds()
	
	logCtx := &LogContext{
		RequestId: r.GetHeader("X-Request-Id"),
		IP:        r.GetClientIp(),
		UserAgent: r.GetHeader("User-Agent"),
		Action:    fmt.Sprintf("%s %s", r.Method, r.URL.Path),
		CostTime:  costTime,
	}
	
	if err != nil {
		logCtx.Error = err.Error()
		l.Error(ctx, "API请求失败", logCtx)
	} else {
		l.Info(ctx, "API请求成功", logCtx)
	}
}

// GetCaller 获取调用者信息
func GetCaller(skip int) (string, string, int) {
	pc, file, line, ok := runtime.Caller(skip)
	if !ok {
		return "", "", 0
	}
	
	func_name := runtime.FuncForPC(pc).Name()
	return func_name, file, line
}

// 预定义的模块日志器
var (
	StockLogger     = New("stock")
	PoolLogger      = New("pool")
	TagLogger       = New("tag")
	StrategyLogger  = New("strategy")
	TradingLogger   = New("trading")
	BacktestLogger  = New("backtest")
	SystemLogger    = New("system")
	DatabaseLogger  = New("database")
	APILogger       = New("api")
)